﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using UCL.Powersource;

namespace PowersourceUIToolkit
{
    public abstract class UIManagerBase : InitializedLifeCycleBase, IUIManager
    {

        
        protected List<IViewConductor> ViewConductors {get;private set;}

        protected UIManagerBase()
        {
            ViewConductors = new List<IViewConductor>();
        }

        
        
        public virtual IViewConductor ActivateViewModelInConductor(IViewModel rootModel, IViewConductor twpcToActivateIn = null)
        {
            if (rootModel == null) throw new ArgumentNullException("rootModel");
            var currentCond = GetConductorForViewModel(rootModel);
            if (currentCond != null)
            {
                if (twpcToActivateIn != null && currentCond != twpcToActivateIn) throw new NotSupportedException(string.Format("Switching between differnt ToolWindowPane is not supported. rootModel {0} is already in ToolWindowPaneConductor {1}[hc:{2}]", rootModel.GetType(), currentCond.GetType(), currentCond.GetHashCode()));
                twpcToActivateIn = currentCond;
            }
            if (twpcToActivateIn == null) throw new InvalidOperationException(string.Format("Unable to find conductor for viewmodel {0} to activate in", rootModel.GetType()));
            if (!ViewConductors.Contains(twpcToActivateIn)) ViewConductors.Add(twpcToActivateIn);
            twpcToActivateIn.ActivateViewModel(rootModel);
            return twpcToActivateIn;

        }

        public virtual IViewConductor GetConductorForViewModel(IViewModel rootModel)
        {
            var control = CreateDefaultControlForViewModel((IViewModel)rootModel);
            var itForFE = ViewLocator.GetViewCacheItem(control);
            //Querying all conductors to find if any holds the reference to ViewCacheItem
            return ViewConductors.FirstOrDefault(a => a.ContainsViewModel(rootModel));

        }

        public virtual Control GetOrCreateControl(object rootModel)
        {

            if (rootModel == null) throw new ArgumentNullException("rootModel");
            if (!(rootModel is IViewModel)) throw new NotSupportedException("Only rootModels of type ViewModel are currently supported");
            return CreateDefaultControlForViewModel((IViewModel)rootModel);

        }

        private Control CreateDefaultControlForViewModel(IViewModel rootModel)
        {
            var view = ViewLocator.CreateOrGetDefaultView(rootModel);

            return (Control)view;
        }

        public abstract IViewConductor GetViewConductor<T>(T rootControl) where T:class;
        public abstract Type GetViewType<T>(T rootModel) where T : IViewModel;
        public abstract void Bind(IViewModel vm, System.Windows.FrameworkElement iview, object context);

        protected override void OnDisposing()
        {
            if (ViewConductors != null)
            {
                foreach (var twpc in ViewConductors)
                {
                    twpc.Dispose();
                }
                ViewConductors.Clear();
                ViewConductors = null;
            }
            
        }

        public void EnsureConductorRegistered(ViewConductorBase viewConductorBase)
        {
            if (!ViewConductors.Contains(viewConductorBase)) ViewConductors.Add(viewConductorBase);
        }
    }
}
